#include "PersistentList.h"
#include <vector>
#include <QList>
#include "stdio.h"
namespace clojure_lang {

PersistentList::PersistentList(CjObject *first)
{
        _first = first;
        _rest = NULL;
	_count = 1;
}


PersistentList::~PersistentList(void)
{
}

IPersistentList *PersistentList::create(QList<CjObject *> *init)
{
        IPersistentList *ret = new EmptyList();
        for (int i = init->count() - 1; i >= 0; --i) {
            IPersistentCollection *tmp = ret->cons(init->at(i));
            ret = dynamic_cast<IPersistentList *>(tmp);
            }
	return ret;

}

IPersistentList *PersistentList::create(std::vector<CjObject *> *init)
{
        IPersistentList *ret = new EmptyList();
	for (int i = init->size() - 1; i >= 0; --i)
                ret = dynamic_cast<IPersistentList *>(ret->cons(init->at(i)));
	return ret;

}

CjObject *PersistentList::peek()
{
        return _first;
}

IPersistentStack *PersistentList::pop()
{
        return _rest == NULL
                ? (new EmptyList)->withMeta(meta())->dynamicCast<IPersistentStack>()
                : dynamic_cast<IPersistentStack *>(_rest);
}


CjObject *PersistentList::first()
{
	return _first;
}


ISeq *PersistentList::next()
{
	if ( _count == 1)
                return NULL;
	return _rest->seq();

}

CjObject *PersistentList::withMeta(IPersistentMap *meta)
{
    if (meta != _meta)
        return  new PersistentList(meta, _first, _rest, _count);
    return this;
}

PersistentList::PersistentList(IPersistentMap *meta, CjObject *first, IPersistentList *rest, int count) : ASeq(meta)
{
    _first = first;
    _rest = rest;
    _count = count;
}


IPersistentCollection *PersistentList::cons(CjObject *o)
{
    return new PersistentList(meta(), o, this->dynamicCast<PersistentList>(), _count + 1);

}

int PersistentList::count()
{
    return _count;
}

CjObject *PersistentList::Ctor::invoke(IPersistentList *lst)
{
    return dynamic_cast<CjObject *>(lst);
}

PersistentList *operator <<(PersistentList &p, CjObject *obj)
{
    return dynamic_cast<PersistentList *>(p.cons(obj));
}

PersistentList::Ctor PersistentList::createEx;

}
